<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <p data-lake-id="uc053d502" id="uc053d502"><span data-lake-id="u5aebca30" id="u5aebca30">在分库分表的过程中，我们需要有一个字段用来进行分表，比如按照用户分表、按照时间分表、按照地区分表。这里面的用户、时间、地区就是所谓的分表字段。</span></p>
  <p data-lake-id="u3dd981df" id="u3dd981df"><br></p>
  <p data-lake-id="u8b49713d" id="u8b49713d"><span data-lake-id="uf1d89250" id="uf1d89250">那么，</span><strong><span data-lake-id="ub724e107" id="ub724e107">在选择这个分表字段的时候，一定要注意，要根据实际的业务情况来做慎重的选择。</span></strong></p>
  <p data-lake-id="u930fd5ea" id="u930fd5ea"><br></p>
  <p data-lake-id="u6391611c" id="u6391611c"><span data-lake-id="u4f8a78cc" id="u4f8a78cc">比如说我们要对交易订单进行分表的时候，我们可以选择的信息有很多，比如买家Id、卖家Id、订单号、时间、地区等等，具体应该如何选择呢？</span></p>
  <p data-lake-id="u5debc141" id="u5debc141"><br></p>
  <p data-lake-id="ue8722e78" id="ue8722e78"><span data-lake-id="u3990d9b1" id="u3990d9b1">通常，如果有特殊的诉求，比如按照月度汇总、地区汇总等以外，我们通常建议大家按照买家Id进行分表。因为这样可以避免一个关键的问题那就是——数据倾斜（热点数据）。</span></p>
  <p data-lake-id="u8ab6fc84" id="u8ab6fc84"><span data-lake-id="u13a5de5c" id="u13a5de5c">​</span><br></p>
  <p data-lake-id="u1da3e50d" id="u1da3e50d"><br></p>
  <h3 data-lake-id="IKrE3" id="IKrE3"><span data-lake-id="ua0ece9d2" id="ua0ece9d2">买家还是卖家</span></h3>
  <p data-lake-id="u35127f05" id="u35127f05"><br></p>
  <p data-lake-id="u0763e722" id="u0763e722"><span data-lake-id="uc3869ddc" id="uc3869ddc">首先，我们先说为什么不按照卖家分表？</span></p>
  <p data-lake-id="u8cd82aba" id="u8cd82aba"><br></p>
  <p data-lake-id="u507ee8ff" id="u507ee8ff"><span data-lake-id="u8dfb5220" id="u8dfb5220">因为我们知道，电商网站上面是有很多买家和卖家的，但是，一个大的卖家可能会产生很多订单，比如像苏宁易购、当当等这种店铺，他每天在天猫产生的订单量就非常的大。如果按照卖家Id分表的话，那同一个卖家的很多订单都会分到同一张表。</span></p>
  <p data-lake-id="u6dafe634" id="u6dafe634"><br></p>
  <p data-lake-id="u802773e7" id="u802773e7"><span data-lake-id="ua8348c2d" id="ua8348c2d">那就会使得有一些表的数据量非常的大，但是有些表的数据量又很小，这就是发生了</span><strong><span data-lake-id="u721db5b8" id="u721db5b8">数据倾斜</span></strong><span data-lake-id="ua89561de" id="ua89561de">。这个卖家的数据就变成了热点数据，随着时间的增长，就会使得这个卖家的所有操作都变得异常缓慢。</span></p>
  <p data-lake-id="uf80d3645" id="uf80d3645"><br></p>
  <p data-lake-id="uf55a7b3d" id="uf55a7b3d"><img src="https://cdn.nlark.com/yuque/0/2023/jpeg/5378072/1673157703302-18f52406-82c1-4c68-9da0-9ccb46da7081.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_33%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ub146d951" id="ub146d951"><br></p>
  <p data-lake-id="u35623948" id="u35623948"><span data-lake-id="ud497f72c" id="ud497f72c">但是，买家ID做分表字段就不会出现这类问题，因为不太容易出现一个买家能把数据买倾斜了。</span></p>
  <p data-lake-id="u09dc91fe" id="u09dc91fe"><br></p>
  <p data-lake-id="u21118bea" id="u21118bea"><span data-lake-id="ub50c1823" id="ub50c1823">但是需要注意的是，</span><strong><span data-lake-id="u60fbf1b8" id="u60fbf1b8">我们说按照买家Id做分表，保证的是同一个买家的所有订单都在同一张表 ，并不是要给每个买家都单独分配一张表。</span></strong></p>
  <p data-lake-id="u4f5f7ebd" id="u4f5f7ebd"><br></p>
  <p data-lake-id="u79dbb1ce" id="u79dbb1ce"><span data-lake-id="uee841a05" id="uee841a05">我们在做分表路由的时候，是可以设定一定的规则的，比如我们想要分1024张表，那么我们可以用买家ID或者买家ID的hashcode对1024取模，结果是0000-1023，那么就存储到对应的编号的分表中就行了。</span></p>
  <p data-lake-id="uc68b9043" id="uc68b9043"><br></p>
  <h3 data-lake-id="LDks0" id="LDks0"><span data-lake-id="u6a66b108" id="u6a66b108">卖家查询怎么办</span></h3>
  <p data-lake-id="u77f6b176" id="u77f6b176"><br></p>
  <p data-lake-id="u9e41b40f" id="u9e41b40f"><span data-lake-id="u7af9f355" id="u7af9f355">如果按照买家Id进行了分表，那卖家的查询怎么办，这不就意味着要跨表查询了吗？</span></p>
  <p data-lake-id="u330e869c" id="u330e869c"><br></p>
  <p data-lake-id="u6a9900a5" id="u6a9900a5"><span data-lake-id="uba4b57f3" id="uba4b57f3">首先，业务问题我们要建立在业务背景下讨论。电商网站订单查询有几种场景？</span></p>
  <p data-lake-id="u5aec65b2" id="u5aec65b2"><br></p>
  <p data-lake-id="u5d9b7194" id="u5d9b7194"><span data-lake-id="ud4753510" id="ud4753510">1、买家查自己的订单</span></p>
  <p data-lake-id="u0b66b411" id="u0b66b411"><br></p>
  <p data-lake-id="uc3d1d368" id="uc3d1d368"><span data-lake-id="ufb6f21af" id="ufb6f21af">2、卖家查自己的订单</span></p>
  <p data-lake-id="u4098bb55" id="u4098bb55"><br></p>
  <p data-lake-id="u670715b5" id="u670715b5"><span data-lake-id="ue5c80e56" id="ue5c80e56">3、平台的小二查用户的订单。</span></p>
  <p data-lake-id="ue0d739c1" id="ue0d739c1"><br></p>
  <p data-lake-id="u3d1136f1" id="u3d1136f1"><span data-lake-id="ufde70c5a" id="ufde70c5a">首先，我们用买家ID做了分表，那么买家来查询的时候，是一定可以把买家ID带过来的，我们直接去对应的表里面查询就行了。</span></p>
  <p data-lake-id="u264a8a04" id="u264a8a04"><br></p>
  <p data-lake-id="u2aa475b4" id="u2aa475b4"><span data-lake-id="u29afd9f5" id="u29afd9f5">那如果是卖家查呢？卖家查询的话，同样可以带卖家id过来，那么，我们可以有一个基于binlog、flink等准实时的同步一张卖家维度的分表，这张表只用来查询，来解决卖家查询的问题。</span></p>
  <p data-lake-id="u9dccd112" id="u9dccd112"><br></p>
  <p data-lake-id="uaa92e044" id="uaa92e044"><img src="https://cdn.nlark.com/yuque/0/2023/jpeg/5378072/1673157703326-00e01824-cc62-4e43-aff0-b838cd8235c2.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u301ca283" id="u301ca283"><br></p>
  <p data-lake-id="u74d55f3e" id="u74d55f3e"><span data-lake-id="ufb83618c" id="ufb83618c">本质上就是用空间换时间的做法。</span></p>
  <p data-lake-id="udd7f1fc2" id="udd7f1fc2"><br></p>
  <p data-lake-id="u6e25f677" id="u6e25f677"><span data-lake-id="u3b8c1dd9" id="u3b8c1dd9">不知道大家看到这里会不会有这样的疑问：同步一张卖家表，这不又带来了大卖家的热点问题了吗？</span></p>
  <p data-lake-id="uc1a207c7" id="uc1a207c7"><br></p>
  <p data-lake-id="ueb686d3d" id="ueb686d3d"><span data-lake-id="uc4dda388" id="uc4dda388">首先，我们说同步一张卖家维度的表来，但是其实所有的写操作还是要写到买家表的，只不过需要准实时同步的方案同步到卖家表中。也就是说，我们的这个卖家表理论上是没有业务的写操作，只有读操作的。</span></p>
  <p data-lake-id="uf2ef9d8c" id="uf2ef9d8c"><br></p>
  <p data-lake-id="u9db2101c" id="u9db2101c"><span data-lake-id="uc02c4748" id="uc02c4748">所以，这个卖家库只需要有高性能的读就行了，那这样的话就可以有很多选择了，比如可以部署到一些配置不用那么高的机器、或者其实可以干脆就不用MYSQL，而是采用HBASE、PolarDB、Lindorm等数据库就可以了。这些数据库都是可以海量数据，并提供高性能查询的。</span></p>
  <p data-lake-id="u49fa6aa1" id="u49fa6aa1"><br></p>
  <p data-lake-id="udde3958a" id="udde3958a"><span data-lake-id="u29b6a6e6" id="u29b6a6e6">还有呢就是，大卖家一般都是可以识别的，提前针对大卖家，把他的订单，再按照一定的规则拆分到多张表中。因为只有读，没有写操作，所以拆分多张表也不用考虑事务的问题。</span></p>
  <p data-lake-id="uf6a1e503" id="uf6a1e503"><span data-lake-id="ua2d4dd9c" id="ua2d4dd9c">​</span><br></p>
  <blockquote data-lake-id="u8cc66d6e" id="u8cc66d6e">
   <p data-lake-id="u0c6e7c4e" id="u0c6e7c4e"><span data-lake-id="u90f36538" id="u90f36538">这里说的没有写指的是不会主动操作这张卖家表做更新，他的数据都是从买家表同步过来的，这个同步的事务在买家表已经处理过了，卖家表只需要负责同步。</span></p>
   <p data-lake-id="u1cfa6644" id="u1cfa6644"><span data-lake-id="uda78d0f2" id="uda78d0f2">​</span><br></p>
   <p data-lake-id="u5e35defa" id="u5e35defa"><span data-lake-id="u749af3e0" id="u749af3e0">卖家更新数据也一样，都是基于订单号更新的，订单号上面是带来分表信息的，直接到买家表去更新，然后同步到卖家表。</span></p>
  </blockquote>
  <p data-lake-id="u11c456d3" id="u11c456d3"><br></p>
  <h3 data-lake-id="RQJEr" id="RQJEr"><span data-lake-id="u239ef38e" id="u239ef38e">订单查询怎么办</span></h3>
  <p data-lake-id="u5912e025" id="u5912e025"><br></p>
  <p data-lake-id="uec108158" id="uec108158"><span data-lake-id="u2d939aaf" id="u2d939aaf">上面说的都是有买卖家ID的情况，那没有买卖家ID呢？用订单号直接查怎么办呢？</span></p>
  <p data-lake-id="u88c7f081" id="u88c7f081"><br></p>
  <p data-lake-id="u8fd1b4a6" id="u8fd1b4a6"><span data-lake-id="u4c66140e" id="u4c66140e">这种问题的解决方案是，在生成订单号的时候，我们一般会把分表结果编码到订单号中去，因为订单生成的时候是一定可以知道买家ID的，那么我们就把买家ID的路由结果比如1023，作为一段固定的值放到订单号中就行了。这就是所谓的</span><strong><span data-lake-id="u98dbe3bc" id="u98dbe3bc">"基因法"</span></strong></p>
  <p data-lake-id="ub54c4f2b" id="ub54c4f2b"><br></p>
  <p data-lake-id="uaba74fe8" id="uaba74fe8"><img src="https://cdn.nlark.com/yuque/0/2023/jpeg/5378072/1673157703285-38d12cf8-6122-4d2e-b8f0-4389488e4099.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_58%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u9d219442" id="u9d219442"><br></p>
  <p data-lake-id="u326ef17d" id="u326ef17d"><span data-lake-id="u1c393777" id="u1c393777">这样按照订单号查询的时候，解析出这段数字，直接去对应分表查询就好了。</span></p>
  <p data-lake-id="u93ae0b07" id="u93ae0b07"><br></p>
  <p data-lake-id="u7dd95755" id="u7dd95755"><span data-lake-id="u5e6e2a2f" id="u5e6e2a2f">至于还有人问其他的查询，没有买卖家ID，也没订单号的，那其实就属于是低频查询或者非核心功能查询了，那就可以用ES等搜索引擎的方案来解决了。就不赘述了。</span></p>
 </body>
</html>